﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Web;
using System.Net;
using DevExpress.XtraEditors;
using System.Windows.Forms;
using Newtonsoft.Json.Linq;


namespace NetDiskPRJ.NetDisk
{
    
    /// <summary>
    /// 上传文件客户端
    /// </summary>
    public class UploadFileClient
    {
        string jsonMsg = "";
        string code = "";
        string msg = "";
        bool IsContinueSend = true;//是否继续发送包


        //上传源路径
        public  string Uploadfilepath
        {
            get;
            set;
    
        }
        public decimal  DestFid
        {

            get;
            set;
        }
        /// <summary>
        /// 服务器创建文件夹
        /// </summary>
        /// <param name="DestPath">服务器文件夹路径(绝对路径)</param>
        /// <param name="jsonNetDiskModel">JSON数据</param>
        /// <param name="jsAlert">返回信息</param>
        /// <returns></returns>
        public bool createDirToServer(string DestPath, string jsonNetDiskModel, out string jsAlert, out decimal outFID)
        {
            bool isSuccess = true;
            string errorMessage = "";
            string tmpID = "0";
            if (isSuccess)
            {
                try
                {
                    bool boolValue = false;
                    bool boolValueSpecial = false;
                    Base.GlobalParams.NetDiskServiceSVC.CreateDir(DestPath, out boolValue, out boolValueSpecial);

                }
                catch (Exception ex)
                {
                    isSuccess = false;
                    errorMessage = "服务器创建文件夹过程失败：" + ex.ToString();
                }
            }
            if (isSuccess)
            {
                try
                {
                    tmpID = Base.GlobalParams.NetDiskServiceSVC.AddNetdisk(jsonNetDiskModel);
                }
                catch (Exception ex)
                {
                    isSuccess = false;
                    errorMessage = "数据插入过程错误：" + ex.ToString();
                }
            }
            if (isSuccess)
            {
                jsAlert = "创建成功！";
            }
            else
            {
                jsAlert = errorMessage;
            }
            outFID = decimal.Parse(tmpID);
            return isSuccess;
        }
        ///// <summary>
        ///// 上传单个文件到网盘
        ///// </summary>
        ///// <param name="SrcPath">客户端文件路径(绝对路径)</param>
        ///// <param name="DestPath">服务器文件夹路径(绝对路径)</param>
        ///// <param name="jsonNetDiskModel">JSON数据</param>
        ///// <param name="IsCover">是否覆盖原文件</param>
        ///// <param name="jsAlert">返回信息</param>
        ///// <returns></returns>
        //public bool uploadFileToServer(string SrcPath, string DestPath, string jsonNetDiskModel, bool IsCover, out string jsAlert)
        //{
        //    bool isSuccess = true;
        //    string errorMessage = "";
        //    if (System.IO.File.Exists(SrcPath))
        //    {
        //        string FileName = SrcPath.Substring(SrcPath.LastIndexOf("\\") + 1);
        //        string tempFileName = "";//临时文件名

        //        //先上传文件到服务器临时文件
        //        jsonMsg = Base.GlobalParams.NetDiskServiceSVC.GetTempFileName(FileName);//服务器上的临时文件路径
        //        Common.GlobalUtil.GetJsonMsgResult(jsonMsg, out code, out msg);

        //        if (code != "0")
        //        {
        //            XtraMessageBox.Show(msg, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
        //            isSuccess = false;
        //            jsAlert = msg;
        //        }
        //        else
        //        {
        //            JObject msgObj = JObject.Parse(JObject.Parse(jsonMsg)["msg"].ToString());
        //            tempFileName = msgObj["TempFileName"].ToString();
        //        }
        //        if (isSuccess)
        //        {
        //            try
        //            {
        //                uploadSingle(SrcPath, tempFileName, true);
        //            }
        //            catch (Exception ex)
        //            {
        //                isSuccess = false;
        //                errorMessage = "上传过程错误：" + ex.ToString();
        //            }
        //        }
        //        //再移动文件到网盘
        //        if (isSuccess)
        //        {
        //            try
        //            {
        //                bool boolValue = false;
        //                bool boolValueSpecial = false;
        //                Base.GlobalParams.NetDiskServiceSVC.MoveFile(tempFileName, DestPath, out boolValue, out boolValueSpecial);
        //            }
        //            catch (Exception ex)
        //            {
        //                isSuccess = false;
        //                errorMessage = "服务器复制过程错误：" + ex.ToString();
        //            }
        //        }
        //        //插入数据
        //        if (isSuccess)
        //        {
        //            try
        //            {
        //                if (IsCover)
        //                {
        //                    Base.GlobalParams.NetDiskServiceSVC.AddNetdiskCover(jsonNetDiskModel);
        //                }
        //                else
        //                {
        //                    Base.GlobalParams.NetDiskServiceSVC.AddNetdisk(jsonNetDiskModel);
        //                }
        //            }
        //            catch (Exception ex)
        //            {
        //                isSuccess = false;
        //                errorMessage = "数据插入过程错误：" + ex.ToString();
        //            }
        //        }
        //    }
        //    if (isSuccess)
        //    {
        //        jsAlert = "上传成功！";
        //    }
        //    else
        //    {
        //        jsAlert = errorMessage;
        //    }
        //    return isSuccess;

        //}

        /// <summary>
        /// 上传单个文件
        /// </summary>
        /// <param name="SrcPath">客户端文件路径(绝对路径)</param>
        /// <param name="DestID">服务器文件夹路径编号</param>
        /// <param name="IsSection">是否分段上传</param>
        /// <param name="jsonNetDiskModel">JSON格式单条数据</param>
        /// <param name="jsAlert">数据信息</param>
        /// <param name="offset">分段大小，默认1M</param>
        public bool uploadSingle(string SrcPath, string DestID, bool IsSection,string jsonNetDiskModel, out string jsAlert, int offset = 1048576)
        {
            string url = Base.GlobalParams.NetDiskServiceSVC.GetUploadPostUrl();//网盘httpWebRequest提交地址
            bool isSuccess = true;
            string errorMessage = "";


            string FileName = SrcPath.Substring(SrcPath.LastIndexOf("\\") + 1);
            string tempFileName = "";//临时文件名
            //先上传文件到服务器临时文件
            jsonMsg = Base.GlobalParams.NetDiskServiceSVC.GetTempFileName(FileName);//服务器上的临时文件路径
            Common.GlobalUtil.GetJsonMsgResult(jsonMsg, out code, out msg);

            if (code != "0")
            {
                XtraMessageBox.Show(msg, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                isSuccess = false;
                jsAlert = msg;
            }
            else
            {
                JObject msgObj = JObject.Parse(JObject.Parse(jsonMsg)["msg"].ToString());
                tempFileName = msgObj["TempFileName"].ToString();
            }




            if (isSuccess)
            {
                try
                {
                    FileStream readStream = new FileStream(SrcPath, FileMode.Open, FileAccess.Read);
                    //如果存在同名文件，就先删除此文件
                    bool delReturn = false;
                    bool delReturnSpecial = false;
                    Base.GlobalParams.NetDiskServiceSVC.DelFile(tempFileName, out delReturn, out delReturnSpecial);

                    if (IsSection)
                    {
                        #region 分段上传
                        long position = 0;
                        long _size = readStream.Length;
                        byte[] readBuffer = new byte[offset];
                        int divide = (int)(_size / offset);//前面分为几段
                        int last = (int)(_size % offset);//剩余byte数
                        for (int i = 0; i < divide; i++)
                        {
                            if (IsContinueSend)//如果继续发送
                            {
                                readBuffer = GetFileBloc(SrcPath, position, offset);//分段写入内存

                                if (position == 0)//第一段的时候，需要创建文件
                                {
                                    if (position == divide - 1 && last == 0)//没有剩余byte数并且是最后一段，需要复制文件
                                    {
                                        //通过webservice上传,创建流
                                        SendFile(readBuffer, tempFileName, true, url, true, DestID, jsonNetDiskModel);
                                    }
                                    else
                                    {
                                        //通过webservice上传,创建流
                                        SendFile(readBuffer, tempFileName, true, url, false, DestID, jsonNetDiskModel);
                                    }
                                }
                                else
                                {
                                    if (position == divide - 1 && last == 0)//没有剩余byte数并且是最后一段，需要复制文件
                                    {
                                        //通过webservice上传,创建流
                                        SendFile(readBuffer, tempFileName, false, url, true, DestID, jsonNetDiskModel);
                                    }
                                    else
                                    {
                                        //通过webservice上传，续传流
                                        SendFile(readBuffer, tempFileName, false, url, false, DestID, jsonNetDiskModel);
                                    }
                                }
                            }
                            
                            position += offset;
                        }
                        //剩余byte写入文件
                        if (IsContinueSend)//如果继续发送
                        {
                            readBuffer = GetFileBloc(SrcPath, position, last);
                        
                            if (position == 0)
                            {
                                //通过webservice上传,创建流
                                SendFile(readBuffer, tempFileName, true, url, true, DestID, jsonNetDiskModel);
                            }
                            else
                            {
                                //通过webservice上传，续传流
                                SendFile(readBuffer, tempFileName, false, url, true, DestID, jsonNetDiskModel);
                            }
                        }
                        #endregion
                    }
                    else
                    {
                        #region 整体上传
                        long _size = readStream.Length;
                        byte[] readBuffer = GetFileBloc(SrcPath, 0, _size);
                        readStream.Read(readBuffer, 0, (int)_size);
                        //serviceBLL.uploadSingle(readBuffer, DestPath, true, false);//通过webservice上传
                        SendFile(readBuffer, tempFileName, true, url, true, DestID, jsonNetDiskModel);
                        #endregion
                    }
                    readStream.Close();
                }
                catch (Exception ex)
                {
                    isSuccess = false;
                    errorMessage = ex.ToString();
                }
            }


            if (isSuccess)
            {
                jsAlert = "上传成功！";
            }
            else
            {
                jsAlert = errorMessage;
            }

            return isSuccess;
        }


        /// <summary>
        /// 获取文件二进制块
        /// </summary>
        /// <param name="SrcPath">源文件</param>
        /// <param name="position">分段起始位置</param>
        /// <param name="offset">分段长度</param>
        /// <returns></returns>
        private byte[] GetFileBloc(string SrcPath, long position, long offset)
        {
            FileStream SrcStream = new FileInfo(SrcPath).OpenRead();
            SrcStream.Position = position;
            byte[] SrcBuffer = new byte[offset];
            SrcStream.Read(SrcBuffer, 0, Convert.ToInt32(offset));
            return SrcBuffer;
        }


        /// <summary>
        /// 发送文件流到webservice
        /// </summary>
        /// <param name="readBuffer">文件二进制流</param>
        /// <param name="tempFileName">临时文件路径</param>
        /// <param name="IsCreate">是否新建文件</param>
        /// <param name="url">webservice里的接收url</param>
        /// <param name="IsEnd">是否文件最后的数据流</param>
        /// <param name="url">服务器文件路径</param>
        /// <param name="JsonNetDiskModel">Json格式网盘数据</param>
        /// <param name="IsCancel">是否取消</param>
        /// <returns></returns>
        private string SendFile(byte[] readBuffer, string TempFileName, bool IsCreate, string url, bool IsEnd, string DestID, string JsonNetDiskModel)
        {
            MainForm.mre.WaitOne();
            string fileSize = readBuffer.Length.ToString();

            HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(url);
            myRequest.Method = "POST";
            //myRequest.ContentType = fileType;
            myRequest.ContentLength = readBuffer.Length;
            myRequest.Headers.Add("FileSize", fileSize);
            string tempFileName = HttpUtility.UrlEncode(TempFileName);
            myRequest.Headers.Add("TempFileName", tempFileName);
            myRequest.Headers.Add("IsCreate", IsCreate.ToString());
            myRequest.Headers.Add("IsEnd", IsEnd.ToString());
            string destID = HttpUtility.UrlEncode(DestID);
            myRequest.Headers.Add("DestID", destID);
            string jsonNetDiskModel = HttpUtility.UrlEncode(JsonNetDiskModel);
            myRequest.Headers.Add("JsonNetDiskModel", jsonNetDiskModel);
            myRequest.Headers.Add("IsCancel", Base.GlobalParams.GLOBAL_ISCANCEL.ToString() );

            if (Base.GlobalParams.GLOBAL_ISCANCEL)
            {
                IsContinueSend = false;
            }

            using (Stream newStream = myRequest.GetRequestStream())
            {
                // Send the data.
                newStream.Write(readBuffer, 0, readBuffer.Length);
                newStream.Close();
            }

            // Get response
            HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();
            StreamReader reader = new StreamReader(myResponse.GetResponseStream(), Encoding.UTF8);
            string content = reader.ReadToEnd();
            return content;
        }


        /// <summary>
        /// 计算文件的MD5校验
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public string GetMD5HashFromFile(Stream file)
        {
            try
            {
                System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
                byte[] retVal = md5.ComputeHash(file);

                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < retVal.Length; i++)
                {
                    sb.Append(retVal[i].ToString("x2"));
                }
                return sb.ToString();
            }
            catch (Exception ex)
            {
                throw new Exception("GetMD5HashFromFile() fail,error:" + ex.Message);
            }
        }


        /// <summary>
        /// 计算文件的MD5校验(绝对地址)
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public string GetMD5HashFromFilePath(string path)
        {
            try
            {
                FileStream file = new FileStream(path, FileMode.Open, FileAccess.Read);
                System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
                byte[] retVal = md5.ComputeHash(file);

                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < retVal.Length; i++)
                {
                    sb.Append(retVal[i].ToString("x2"));
                }
                return sb.ToString();
            }
            catch (Exception ex)
            {
                throw new Exception("GetMD5HashFromFilePath() fail,error:" + ex.Message);
            }
        }









    }
}
